package org.example.thymeleaf.demo.demos.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.xmlbeans.XmlOptions;
import org.example.thymeleaf.demo.demos.mapper.WordTemplateMapper;
import org.example.thymeleaf.demo.demos.entity.WordTemplate;
import org.example.thymeleaf.demo.demos.service.WordTemplateService;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * (WordTemplate)表服务实现类
 *
 * @author makejava
 * @since 2024-09-11 09:23:48
 */
@Service("wordTemplateService")
public class WordTemplateServiceImpl extends ServiceImpl<WordTemplateMapper, WordTemplate> implements WordTemplateService {

    @Override
    public byte[] mergeWord(List<byte[]> list) throws IOException {
        // 使用 ByteArrayOutputStream 替代文件输出流
        ByteArrayOutputStream mergedOutputStream = new ByteArrayOutputStream();
        ArrayList<XWPFDocument> documentList = new ArrayList<>();
        XWPFDocument doc = null;
        try {
            // 1. 将每个 byte[] 转换为 XWPFDocument 对象
            for (byte[] docxBytes : list) {
                ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(docxBytes);
                OPCPackage opcPackage = OPCPackage.open(byteArrayInputStream);
                XWPFDocument document = new XWPFDocument(opcPackage);
                documentList.add(document);
            }

            // 2. 开始合并文档
            for (int i = 0; i < documentList.size(); i++) {
                doc = documentList.get(0);  // 初始化 doc 为第一个文档
                if (i == 0) {
                    // 首页直接分页，不插入首页内容
                    documentList.get(i).createParagraph().createRun().addBreak(BreakType.PAGE);
                } else if (i == documentList.size() - 1) {
                    // 尾页不分页，直接插入最后一个文档内容
                    appendBody(doc, documentList.get(i));
                } else {
                    // 中间的文档插入分页符
                    documentList.get(i).createParagraph().createRun().addBreak(BreakType.PAGE);
                    appendBody(doc, documentList.get(i));
                }
            }

            // 3. 将合并后的文档写入到 ByteArrayOutputStream
            doc.write(mergedOutputStream);
            mergedOutputStream.close();

            System.out.println("*****合并成功********");
        }  catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 4. 返回合并后的 byte[]
        return  mergedOutputStream.toByteArray();
//        return new String(mergedOutputStream.toByteArray());
    }



    // 合并文档主体的辅助方法
    public void appendBody(XWPFDocument src, XWPFDocument append) throws Exception {
        CTBody destBody = src.getDocument().getBody();
        CTBody srcBody = append.getDocument().getBody();

        List<XWPFPictureData> allPictures = append.getAllPictures();
        // 记录图片合并前及合并后的ID
        Map<String, String> map = new HashMap<>();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            // 将原文档中的图片加入到目标文档中
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after);
        }
        appendBody(destBody, srcBody, map);
    }

    // 辅助方法：将两个文档的内容拼接
    private void appendBody(CTBody src, CTBody append, Map<String, String> map) throws Exception {
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = append.xmlText(optionsOuter);

        String srcString = src.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
        if (map != null && !map.isEmpty()) {
            // 对xml字符串中图片ID进行替换
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
        }
        // 将两个文档的xml内容进行拼接
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        src.set(makeBody);
    }
}

